function sortTable(dir, col, fromSortedRow, name, cmpr) {

  // Get the table section to sort.
  var tblEl = document.getElementById(name);

  // Set the table display style to "none" - necessary for Netscape 6 
  // browsers.
  var oldDsply = tblEl.style.display;
  tblEl.style.display = "none";
  var tblBody = document.getElementById(name+"_body");
  // Sort the rows based on the content of the specified column
  // using a selection sort.
  var tmpEl;
  var i, j;
  var minVal, minIdx;
  var testVal;
  var cmp;

  for (i = fromSortedRow; i < tblEl.rows.length; i++) {

    // Assume the current row has the minimum value.
    minIdx = i;
    minVal = getTextValue(tblEl.rows[i].cells[col]);

    // Search the rows that follow the current one for a smaller value.
    for (j = i + 1; j < tblEl.rows.length; j++) {
      testVal = getTextValue(tblEl.rows[j].cells[col]);
      cmp = compareValues(minVal, testVal, cmpr);
      // If this row has a smaller value than the current minimum,
      // remember its position and update the current minimum value.
      if (dir) cmp = -cmp;

      if (cmp > 0) {
        minIdx = j;
        minVal = testVal;
      }
    }
    // By now, we have the row with the smallest value. Remove it from
    // the table and insert it before the current row.
    if (minIdx > i) {
      tmpEl = tblBody.removeChild(tblEl.rows[minIdx]);
      tblBody.insertBefore(tmpEl, tblEl.rows[i]);
    }
    var pref = ( (i % 2 == 0 ) ? "light" : "dark" );
    var c = tblEl.rows[i];
    c.className = pref+"Squeeze";

  }
  // Restore the table's display style.
  tblEl.style.display = oldDsply;
  return false;
}
function getTextValue(el)
{
    var values = el.getElementsByTagName("input");
    if (values.length>0)
    {
        var s = "";
        for (var i = 0; i<values.length-1; i++)
            s += values[i].value +" ";
        s += values[values.length-1].value;
        return s;
    }
    else
    {
      return getOtherTextValue(el);
    }
}
function getOtherTextValue(el)
{
  var i;
  var s;

  // Find and concatenate the values of all text nodes contained within the
  // element.
  s = "";
  for (i = 0; i < el.childNodes.length; i++)
    if (el.childNodes[i].nodeType == document.TEXT_NODE || el.childNodes[i].nodeType==3)
      s += el.childNodes[i].nodeValue;
    else if (el.childNodes[i].nodeType == document.ELEMENT_NODE &&
             el.childNodes[i].tagName == "BR")
      s += " ";
    else
      // Use recursion to get text within sub-elements.
      s += getOtherTextValue(el.childNodes[i]);

  return normalizeString(s);        
}
// Regular expressions for normalizing white space.
var whtSpEnds = new RegExp("^\\s*|\\s*$", "g");
var whtSpMult = new RegExp("\\s\\s+", "g");

function normalizeString(s) {

  s = s.replace(whtSpMult, " ");  // Collapse any multiple whites space.
  s = s.replace(whtSpEnds, "");   // Remove leading or trailing white space.

  return s;
}

var strCmpr = new stringComparator();
var intCmpr = new integerComparator();
var floatCmpr = new floatComparator();
var ipCmpr = new IPComparator();

function compareValues(v1, v2, cmpr) {
    return cmpr.compare(v1, v2);
}

